home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / tput-1_0.lha / tput-1.0 / tput.c < prev    next >
C/C++ Source or Header  |  1991-07-10  |  8KB  |  342 lines

  1. /* tput -- shell-level interface to terminfo, emulated by termcap.
  2.    Copyright (C) 1989 Free Software Foundation, Inc.
  3.  
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 2, or (at your option)
  7.    any later version.
  8.  
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.  
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18. /* Usage: tput [-T termtype] [+terminal=termtype] capability [parameter...]
  19.  
  20.    Options:
  21.    -T termtype
  22.    +terminal=termtype    Override $TERM.
  23.  
  24.    Link with -ltermcap.
  25.    Requires the GNU termcap library.
  26.    Also requires the bsearch library function.
  27.  
  28.    David MacKenzie <djm@ai.mit.edu> */
  29.  
  30. #include <stdio.h>
  31. #include <signal.h>
  32. #include <sgtty.h>
  33. #include <termcap.h>
  34. #include <getopt.h>
  35. #include "tput.h"
  36.  
  37. #ifndef SIGTYPE
  38. #define SIGTYPE void
  39. #endif
  40.  
  41. /* Exit codes. */
  42. #define CAP_PRESENT 0        /* Normal operation. */
  43. #define BOOLEAN_FALSE 1        /* Boolean capability not present. */
  44. #define USAGE_ERROR 2        /* Invalid arguments given. */
  45. #define UNKNOWN_TERM 3        /* $TERM not found in termcap file. */
  46. #define MISSING_CAP 4        /* Termcap entry lacks this capability. */
  47. #define ERROR_EXIT 5        /* Real error or signal. */
  48.  
  49. char *bsearch ();
  50. char *getenv ();
  51.  
  52. int info_compare ();
  53. SIGTYPE signal_handler ();
  54. int tcputchar ();
  55. struct conversion *find_info ();
  56. void put_bool ();
  57. void put_num ();
  58. void put_str ();
  59. void restore_translations ();
  60. void translations_off ();
  61. void setup_termcap ();
  62. void usage ();
  63.  
  64. /* The name this program was run with, for error messages. */
  65. char *program_name;
  66.  
  67. struct option long_options[] =
  68. {
  69.   {"terminal", 1, NULL, 0},
  70.   {NULL, 0, NULL, 0}
  71. };
  72.  
  73. void
  74. main (argc, argv)
  75.      int argc;
  76.      char **argv;
  77. {
  78.   struct conversion *conv;    /* Conversion table entry. */
  79.   char *term;            /* Terminal type. */
  80.   int c;            /* Option character. */
  81.  
  82.   program_name = argv[0];
  83.   term = getenv ("TERM");
  84.  
  85.   while ((c = getopt_long (argc, argv, "T:", long_options, (int *) 0)) != EOF)
  86.     {
  87.       switch (c)
  88.     {
  89.     case 0:
  90.       break;
  91.  
  92.     case 'T':
  93.       term = optarg;
  94.       break;
  95.  
  96.     default:
  97.       usage ();
  98.     }
  99.     }
  100.  
  101.   if (optind == argc)
  102.     usage ();
  103.  
  104.   setup_termcap (term);
  105.  
  106.   conv = find_info (argv[optind]);
  107.   if (conv == NULL)
  108.     {
  109.       fprintf (stderr, "%s: Unknown terminfo capability `%s'\n",
  110.            program_name, argv[optind]);
  111.       exit (MISSING_CAP);
  112.     }
  113.  
  114.   ++optind;
  115.  
  116.   if (conv->type & NUM)
  117.     put_num (conv);
  118.   else if (conv->type & BOOL)
  119.     put_bool (conv);
  120.   else
  121.     put_str (conv, argv, argc);
  122.  
  123.   exit (CAP_PRESENT);
  124. }
  125.  
  126. /* Return a pointer to the conversion table entry for terminfo
  127.    capability INFONAME.
  128.    Return NULL if INFONAME is not a valid terminfo capability. */
  129.  
  130. struct conversion *
  131. find_info (infoname)
  132.      char *infoname;
  133. {
  134.   struct conversion conv;
  135.  
  136.   conv.info = infoname;
  137.   return (struct conversion *)
  138.     bsearch ((char *) &conv, (char *) conversions, CAPABILITIES,
  139.          sizeof (struct conversion), info_compare);
  140. }
  141.  
  142. /* Terminfo capability name comparison function for bsearch. */
  143.  
  144. int
  145. info_compare (conv1, conv2)
  146.      struct conversion *conv1, *conv2;
  147. {
  148.   return strcmp (conv1->info, conv2->info);
  149. }
  150.  
  151. void
  152. put_num (conv)
  153.      struct conversion *conv;
  154. {
  155.   printf ("%d\n", tgetnum (conv->cap));
  156. }
  157.  
  158. void
  159. put_bool (conv)
  160.      struct conversion *conv;
  161. {
  162.   if (!tgetflag (conv->cap))
  163.     exit (BOOLEAN_FALSE);
  164. }
  165.  
  166. void
  167. put_str (conv, argv, argc)
  168.      struct conversion *conv;
  169.      char **argv;
  170.      int argc;
  171. {
  172.   char *string_value;        /* String capability. */
  173.   int lines_affected;        /* Number of lines affected by capability. */
  174.  
  175.   string_value = tgetstr (conv->cap, (char **) NULL);
  176.   if (string_value == NULL)
  177.     exit (MISSING_CAP);
  178.  
  179.   if (!strcmp (conv->cap, "cm"))
  180.     {
  181.       BC = tgetstr ("le", (char **) NULL);
  182.       UP = tgetstr ("up", (char **) NULL);
  183.  
  184.       /* The order of command-line arguments is `vertical horizontal'.
  185.      If horizontal is not given, it defaults to 0. */
  186.       switch (argc - optind)
  187.     {
  188.     case 0:
  189.       break;
  190.     case 1:
  191.       string_value = tgoto (string_value, 0, atoi (argv[optind]));
  192.       break;
  193.     default:
  194.       string_value = tgoto (string_value,
  195.                   atoi (argv[optind + 1]), atoi (argv[optind]));
  196.       break;
  197.     }
  198.     }
  199.   else
  200.     /* Although the terminfo `sgr' capability can take 9 parameters,
  201.        the GNU tparam function only accepts up to 4.
  202.        I don't know whether tparam could interpret an `sgr'
  203.        capability reasonably even if it could accept that many
  204.        parameters.  For now, we'll live with the 4-parameter limit. */
  205.     switch (argc - optind)
  206.       {
  207.       case 0:
  208.     break;
  209.       case 1:
  210.     string_value = tparam (string_value, (char *) NULL, 0,
  211.                    atoi (argv[optind]));
  212.     break;
  213.       case 2:
  214.     string_value = tparam (string_value, (char *) NULL, 0,
  215.                    atoi (argv[optind]),
  216.                    atoi (argv[optind + 1]));
  217.     break;
  218.       case 3:
  219.     string_value = tparam (string_value, (char *) NULL, 0,
  220.                    atoi (argv[optind]),
  221.                    atoi (argv[optind + 1]),
  222.                    atoi (argv[optind + 2]));
  223.     break;
  224.       default:
  225.     string_value = tparam (string_value, (char *) NULL, 0,
  226.                    atoi (argv[optind]),
  227.                    atoi (argv[optind + 1]),
  228.                    atoi (argv[optind + 2]),
  229.                    atoi (argv[optind + 3]));
  230.     break;
  231.       }
  232.  
  233.   /* Since we don't know where the cursor is, we have to be
  234.      pessimistic for capabilities that need padding proportional to
  235.      the number of lines affected, and tell them that the whole
  236.      screen is affected.  */
  237.   if (conv->type & PAD)
  238.     lines_affected = tgetnum ("li");
  239.   else
  240.     lines_affected = 1;
  241.  
  242.   if (lines_affected < 1)
  243.     lines_affected = 1;
  244.  
  245.   translations_off ();
  246.   tputs (string_value, lines_affected, tcputchar);
  247.   fflush (stdout);
  248.   restore_translations ();
  249. }
  250.  
  251. /* Output function for tputs.  */
  252.  
  253. int
  254. tcputchar (c)
  255.      char c;
  256. {
  257.   putchar (c & 0x7f);
  258.   return c;
  259. }
  260.  
  261. /* Read in the needed termcap strings for terminal type TERM. */
  262.  
  263. void
  264. setup_termcap (term)
  265.      char *term;
  266. {
  267.   char *tc_pc;            /* "pc" termcap string. */
  268.  
  269.   if (term == NULL)
  270.     {
  271.       fprintf (stderr, "%s: No value for $TERM and no -T specified\n",
  272.            program_name);
  273.       exit (UNKNOWN_TERM);
  274.     }
  275.   switch (tgetent ((char *) NULL, term))
  276.     {
  277.     case 0:
  278.       fprintf (stderr, "%s: Unknown terminal type `%s'\n", program_name, term);
  279.       exit (UNKNOWN_TERM);
  280.     case -1:
  281.       fprintf (stderr, "%s: No termcap database\n", program_name);
  282.       exit (UNKNOWN_TERM);
  283.     }
  284.  
  285.   tc_pc = tgetstr ("pc", (char **) NULL);
  286.   PC = tc_pc ? *tc_pc : 0;
  287. }
  288.  
  289. struct sgttyb old_modes, new_modes;
  290.  
  291. /* Turn off expansion of tabs into spaces, saving the old
  292.    terminal settings first.
  293.    Also set OSPEED.  */
  294.  
  295. void
  296. translations_off ()
  297. {
  298.   if (isatty (1))
  299.     {
  300.       gtty (1, &old_modes);
  301.  
  302.       if (signal (SIGINT, SIG_IGN) != SIG_IGN)
  303.     signal (SIGINT, signal_handler);
  304.       if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
  305.     signal (SIGHUP, signal_handler);
  306.       if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
  307.     signal (SIGQUIT, signal_handler);
  308.       signal (SIGTERM, signal_handler);
  309.  
  310.       new_modes = old_modes;
  311.       new_modes.sg_flags &= ~XTABS;
  312.       stty (1, &new_modes);
  313.       ospeed = old_modes.sg_ospeed;
  314.     }
  315.   else
  316.     ospeed = 0;
  317. }
  318.  
  319. /* Restore the old terminal settings.  */
  320.  
  321. void
  322. restore_translations ()
  323. {
  324.   stty (1, &old_modes);
  325. }
  326.  
  327. SIGTYPE
  328. signal_handler ()
  329. {
  330.   restore_translations ();
  331.   exit (ERROR_EXIT);
  332. }
  333.  
  334. void
  335. usage ()
  336. {
  337.   fprintf (stderr, "\
  338. Usage: %s [-T termtype] [+terminal=termtype] capability [parameter...]\n",
  339.        program_name);
  340.   exit (USAGE_ERROR);
  341. }
  342.